#include<stdio.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include"terminal_ptty.h"
#include<sys/wait.h>
#include<sys/pty.h>
#include<signal.h>

terminal_ptty_t pty;

int terminal_ptty_init()
{
    // create tty
    int fdm = posix_openpt(O_RDWR);
    if (fdm<0)
    {
        printf("[terminal] open tty failed!\n");
        return -1;
    }
    unlockpt(fdm);

    uint32_t flags=PTTY_RDNOBLK;
    ioctl(fdm,TTYIO_SETFLAGS,&flags);

    pty.fd_master=fdm;
    pty.init=1;
    pty.pid_slaver=-1;

    dprintf("[terminal] pty fd master %d\n",pty.fd_master);
    return 0;
}

void exit_ptty()
{
    kill(pty.pid_slaver,SIGKILL);
    waitpid(pty.pid_slaver,NULL,WNOHANG);
}

void terminal_ptty_setup(pid_t pid)
{
    pty.pid_slaver=pid;
    atexit(exit_ptty);
}

int terminal_ptty_launch(terminal_ptty_t *pty,char *pathname)
{
    if(!pty->init)
        return -1; 
    char *sname=ptsname(pty->fd_master);
    if(!sname)
    {
        dprintf("terminal: %s: get slaver name failed\n",__func__);
        return -1;
    }

    #ifdef  DEBUG_TERMINAL
    dprintf("terminal: slaver %s\n",sname);
    #endif

    int fds=open(sname,O_RDWR|O_NONBLOCK);
    if(fds<0)
    {
        dprintf("terminal: %s: open slave device err\n",__func__);
        return -1;
    }

     // set new group
    setpgrp();
    tcsetpgrp(pty, getpgrp());

    dup2(fds, __stdio_get_stdin()->fd);
    dup2(fds, __stdio_get_stdout()->fd);
    dup2(fds, __stdio_get_stderr()->fd);
    
    dprintf("terminal: start exec shell %s\n",pathname);
    char *_argv[2] = {pathname, NULL};
    execv(pathname,_argv);
    dprintf("terminal: %s: execute shell %s failed\n",__func__,pathname);
    exit(-1);
    return -1;
}

int terminal_ptty_exit(terminal_ptty_t *pty)
{
    if(!pty->init)
        return -1;
    close(pty->fd_master);
    return 0;
}